package controllers

import (
	"acs/management/models"
	"acs/pbmodel"
	"acs/taskprocess"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"regexp"
	"strconv"
	"strings"

	"github.com/labstack/echo"
	"gopkg.in/mgo.v2/bson"
	"gopkg.in/vmihailenco/msgpack.v2"
)

//UploadUpvFile 通过上传包含用户更新app补丁的数组txt
func UploadUpvFile(c echo.Context) error {
	defer models.ErrorHandler(c)
	md5 := c.FormValue("md5")
	url := c.FormValue("url")
	size := c.FormValue("size")
	userCount, upverr := upvUpload(c, md5, url, size)
	models.CheckError(upverr)
	currentUser := models.CheckLogin(c)
	models.AppendLog(&currentUser, "加入推送队列的人数:"+strconv.Itoa(userCount), models.LOG_TYPE_PUSH_PATCH_SCHEMA)
	c.JSON(http.StatusOK, "加入推送队列的人数:"+strconv.Itoa(userCount))
	return nil
}

//上传用户列表的文件。以及推送到nsq服务器
func upvUpload(c echo.Context, md5, url, size string) (int, error) {
	defer models.ErrorHandler(c)

	useridFileHeader, err := c.FormFile("useridFile")
	if err != nil {
		return 0, err
	}
	useridFile, fileErr := useridFileHeader.Open()
	if fileErr != nil {
		return 0, fileErr
	}
	fd, fderr := ioutil.ReadAll(useridFile)
	if fderr != nil {
		return 0, fderr
	}
	allUserIDListStr := string(fd)
	allUserIDList := strings.Split(allUserIDListStr, ",")
	taskProtoNew := taskprocess.TaskInQueue{}
	bundleid := c.FormValue("bundleid")

	app, appErr := models.GetTAppByBundId(bundleid)
	if appErr != nil {
		return 0, appErr
	}
	fmt.Println(app)
	if app.Enable == 0 {
		return 0, errors.New("此app已经禁用了")
	}
	typeValue := c.FormValue("typeValue")
	platform := c.FormValue("platform")
	tPatchID := c.FormValue("tPatchID")
	patchID, patchIDErr := strconv.Atoi(tPatchID)
	if patchIDErr != nil {
		return 0, patchIDErr
	}
	patch, patcherr := models.GetTPatchById(int64(patchID))
	if patcherr != nil {
		return 0, patcherr
	}
	if patch.Enable == 0 {
		return 0, errors.New("此补丁已经禁用了")
	}
	desc := c.FormValue("desc")
	prevPatchID := c.FormValue("prevPatchID")
	intType, typeErr := strconv.Atoi(typeValue)
	if typeErr != nil {
		return 0, typeErr
	}
	taskProtoNew.Type = taskprocess.TaskType(intType)

	intPlatform, platformErr := strconv.Atoi(platform)
	if platformErr != nil {
		return 0, platformErr
	}
	var useridList []string
	for _, useridstr := range allUserIDList {

		matched, matcherr := regexp.Match(models.Conf.NsqUpv.Nsq_upv_uid_regexp, []byte(useridstr))
		if matcherr != nil {
			return 0, matcherr
		}
		if matched == false {
			return 0, errors.New("uid 格式不符合")
		}
		useridList = append(useridList, useridstr)
	}
	if taskProtoNew.Type == taskprocess.TaskTypePatch {
		// 如果是 patch 补丁
		task := &taskprocess.PatchTask{}
		task.BundleID = bundleid
		task.PrevPatchID = prevPatchID
		task.Platform = taskprocess.AppPlatform(intPlatform)
		task.PatchID = &tPatchID
		int64size, sizeerr := strconv.ParseInt(string(size), 10, 64)
		if sizeerr != nil {
			return 0, sizeerr
		}
		var patch pbmodel.Patch
		uint64size := uint64(int64size)
		patch.Size = &(uint64size)
		patch.Md5 = &md5
		url = models.Conf.JumeiPicsystem.Jumei_picsystem_CDN + url
		patch.Url = &url
		patch.Desc = &desc
		task.Patch = patch
		task.TargetUID = useridList
		rb, patcherr := msgpack.Marshal(task)
		if patcherr != nil {
			return 0, patcherr
		}
		taskProtoNew.RawBytes = rb
	} else if taskProtoNew.Type == taskprocess.TaskTypeSchema {
		// 如果是 schema 配置文件。
		schemaTask := &taskprocess.SchemaTask{}
		schemaTask.BundleID = bundleid
		schemaTask.Platform = taskprocess.AppPlatform(intPlatform)
		schemaTask.PrevSchemaID = prevPatchID
		schemaTask.TargetUID = useridList
		//	var thisSchema pbmodel.Schema
		schemaTask.SchemaID = &tPatchID
		schemaTask.Md5 = &md5
		url = models.Conf.JumeiPicsystem.Jumei_picsystem_CDN + url
		schemaTask.Url = &url
		//schemaTask.Schema = thisSchema
		schemaTask.Desc = &desc
		rb, schemaerr := msgpack.Marshal(schemaTask)
		if schemaerr != nil {
			return 0, schemaerr
		}
		taskProtoNew.RawBytes = rb
	}
	tb, tberr := msgpack.Marshal(taskProtoNew)
	if tberr != nil {
		return 0, tberr
	}

	var tempTaskqueue taskprocess.TaskInQueue
	err = msgpack.Unmarshal(tb, &tempTaskqueue)
	if err != nil {
		return 0, err
	}
	var tempschemaTask taskprocess.SchemaTask
	err = msgpack.Unmarshal(tempTaskqueue.RawBytes, &tempschemaTask)
	if err != nil {
		return 0, err
	}
	nsqerr := models.PushUPV2NSQ(tb)
	if nsqerr != nil {
		return 0, nsqerr
	}
	// _, err = models.HandleUPVFromNSQ()
	// models.CheckError(err)
	return len(useridList), nil
}

//PostUserPatchVersion 接收来自业务部门发送过来的客户端版本信息
func PostUserPatchVersion(c echo.Context) (err error) {
	defer models.ErrorHandler(c)
	result, patchErr := receiveAndUploadPatch(c)
	models.CheckError(patchErr)
	userCount, upverr := upvUpload(c, result["md5"], result["url"], result["size"])
	models.CheckError(upverr)
	c.JSON(http.StatusOK, "加入推送队列的人数:"+strconv.Itoa(userCount))
	return
}

//ADDUPVUserTask 手动添加
func ADDUPVUserTask(c echo.Context) (err error) {
	defer models.ErrorHandler(c)
	requestbody, requesterr := ioutil.ReadAll(c.Request().Body())
	models.CheckError(requesterr)
	var thisUpvUserTask models.UpvUserTask
	err = json.Unmarshal(requestbody, &thisUpvUserTask)
	models.CheckError(err)
	thisUpvUserTask.ID = bson.NewObjectId()
	err = models.UPVUserTaskCollection.Insert(&thisUpvUserTask)
	models.CheckError(err)
	c.JSON(http.StatusOK, models.ExportJson(models.Right_Status, nil, thisUpvUserTask, -1))
	return nil
}

//ADDUPVTaskContent 手动添加
func ADDUPVTaskContent(c echo.Context) (err error) {
	defer models.ErrorHandler(c)
	requestbody, requesterr := ioutil.ReadAll(c.Request().Body())
	models.CheckError(requesterr)
	var thisUpvTaskContent models.UpvTask
	err = json.Unmarshal(requestbody, &thisUpvTaskContent)
	models.CheckError(err)
	thisUpvTaskContent.ID = bson.NewObjectId()
	err = models.UPVTaskContentCollection.Insert(&thisUpvTaskContent)
	models.CheckError(err)
	c.JSON(http.StatusOK, models.ExportJson(models.Right_Status, nil, thisUpvTaskContent, -1))
	return nil
}

//GetUPVUserTask 根据id获取user_task
func GetUPVUserTask(c echo.Context) (err error) {
	defer models.ErrorHandler(c)
	operationIDStr := c.Param("id")
	objectID := bson.ObjectIdHex(operationIDStr)
	queryBson := bson.M{"_id": objectID}
	result := new(models.UpvUserTask)
	err = models.UPVUserTaskCollection.Find(queryBson).One(result)
	models.CheckError(err)
	c.JSON(http.StatusOK, models.ExportJson(models.Right_Status, nil, result, -1))
	return nil
}

//GetUPVTaskContent 根据id获取task_content
func GetUPVTaskContent(c echo.Context) (err error) {
	defer models.ErrorHandler(c)
	operationIDStr := c.Param("id")
	objectID := bson.ObjectIdHex(operationIDStr)
	queryBson := bson.M{"_id": objectID}
	result := new(models.UpvTask)
	err = models.UPVTaskContentCollection.Find(queryBson).One(result)
	models.CheckError(err)
	c.JSON(http.StatusOK, models.ExportJson(models.Right_Status, nil, result, -1))
	return nil
}

//ListUPVUserTask 获取user_task列表
func ListUPVUserTask(c echo.Context) (err error) {
	defer models.ErrorHandler(c)
	currentPageStr := c.Param("page")
	currentPage, switchErr := strconv.Atoi(currentPageStr)
	models.CheckError(switchErr)

	currentStepStr := c.Param("step")
	currentStep, switchErr2 := strconv.Atoi(currentStepStr)
	models.CheckError(switchErr2)
	if currentPage < 1 || currentStep < 1 {
		panic(errors.New("参数不符合标准。"))
	}

	var result []interface{}
	query := models.UPVUserTaskCollection.Find(nil)
	totalCount, countErr := query.Count()
	models.CheckError(countErr)
	err = query.Skip((currentPage - 1) * currentStep).Limit(currentStep).All(&result)
	models.CheckError(err)
	c.JSON(http.StatusOK, models.ExportJson(models.Right_Status, nil, result, int64(totalCount)))
	return nil
}

//ListUPVTaskContent 获取task_content列表
func ListUPVTaskContent(c echo.Context) (err error) {
	defer models.ErrorHandler(c)
	currentPageStr := c.Param("page")
	currentPage, switchErr := strconv.Atoi(currentPageStr)
	models.CheckError(switchErr)

	currentStepStr := c.Param("step")
	currentStep, switchErr2 := strconv.Atoi(currentStepStr)
	models.CheckError(switchErr2)
	if currentPage < 1 || currentStep < 1 {
		panic(errors.New("参数不符合标准。"))
	}
	var currentUser models.UserWithPirvilege
	currentUser = models.CheckLogin(c)
	api_id := models.GetJumeiApiIDByPath(c.Request().Method(), c.Path())
	allowList, priErr := models.CheckUserPrivilege(&currentUser, models.TableJumeiAPI, api_id, models.RoleRead)
	models.CheckError(priErr)
	if len(allowList) == 0 {
		c.JSON(http.StatusOK, models.ExportJson(models.Right_Status, currentUser, []int{}, -1))
		return
	}

	var result []interface{}
	query := models.UPVTaskContentCollection.Find(nil)
	totalCount, countErr := query.Count()
	models.CheckError(countErr)
	err = query.Skip((currentPage - 1) * currentStep).Limit(currentStep).All(&result)
	models.CheckError(err)
	c.JSON(http.StatusOK, models.ExportJson(models.Right_Status, nil, result, int64(totalCount)))
	return nil
}

//UpdateUPVUserTask 更新upv 的user_task集合
func UpdateUPVUserTask(c echo.Context) (err error) {
	defer models.ErrorHandler(c)
	queryBody, requesterr := ioutil.ReadAll(c.Request().Body())
	models.CheckError(requesterr)
	updateObj := new(models.UpvUserTask)
	err = json.Unmarshal(queryBody, &updateObj)
	models.CheckError(err)
	operationIDStr := c.Param("id")
	objectID := bson.ObjectIdHex(operationIDStr)
	queryBson := bson.M{"_id": objectID}
	err = models.UPVUserTaskCollection.Update(queryBson, updateObj)
	models.CheckError(err)
	c.JSON(http.StatusOK, models.ExportJson(models.Right_Status, nil, updateObj, -1))
	return nil
}

//UpdateUPVTaskContent 更新task_content 集合
func UpdateUPVTaskContent(c echo.Context) (err error) {
	defer models.ErrorHandler(c)
	queryBody, requesterr := ioutil.ReadAll(c.Request().Body())
	models.CheckError(requesterr)
	updateObj := new(models.UpvTask)
	err = json.Unmarshal(queryBody, &updateObj)
	models.CheckError(err)
	operationIDStr := c.Param("id")
	objectID := bson.ObjectIdHex(operationIDStr)
	queryBson := bson.M{"_id": objectID}
	err = models.UPVTaskContentCollection.Update(queryBson, updateObj)
	models.CheckError(err)
	c.JSON(http.StatusOK, models.ExportJson(models.Right_Status, nil, updateObj, -1))
	return nil
}

//DeleteUPVUserTask 删除upv 的user_task集合
func DeleteUPVUserTask(c echo.Context) (err error) {
	defer models.ErrorHandler(c)
	operationIDStr := c.Param("id")
	objectID := bson.ObjectIdHex(operationIDStr)
	queryBson := bson.M{"_id": objectID}
	var currentUser models.UserWithPirvilege
	currentUser = models.CheckLogin(c)
	api_id := models.GetJumeiApiIDByPath(c.Request().Method(), c.Path())
	err = delteUPVUserTask(currentUser, api_id, operationIDStr)
	models.CheckError(err)
	c.JSON(http.StatusOK, models.ExportJson(models.Right_Status, nil, queryBson, -1))
	return nil
}

func delteUPVUserTask(currentUser models.UserWithPirvilege, api_id int, id string) error {
	objectID := bson.ObjectIdHex(id)
	queryBson := bson.M{"_id": objectID}
	allowList, priErr := models.CheckUserPrivilege(&currentUser, models.TableJumeiAPI, api_id, models.RoleDelete)
	if priErr != nil {
		return priErr
	}
	if len(allowList) == 0 {

		return nil
	}
	priErr = models.UPVUserTaskCollection.Remove(queryBson)
	if priErr != nil {
		return priErr
	}
	return nil
}

//DeleteUPVTaskContent 删除task_content 集合
func DeleteUPVTaskContent(c echo.Context) (err error) {
	defer models.ErrorHandler(c)
	operationIDStr := c.Param("id")

	var currentUser models.UserWithPirvilege
	currentUser = models.CheckLogin(c)
	api_id := models.GetJumeiApiIDByPath(c.Request().Method(), c.Path())
	err = delteUPVTaskContent(currentUser, api_id, operationIDStr)
	models.CheckError(err)
	c.JSON(http.StatusOK, models.ExportJson(models.Right_Status, nil, operationIDStr, -1))
	return nil
}
func delteUPVTaskContent(currentUser models.UserWithPirvilege, api_id int, id string) error {
	objectID := bson.ObjectIdHex(id)
	queryBson := bson.M{"_id": objectID}

	allowList, priErr := models.CheckUserPrivilege(&currentUser, models.TableJumeiAPI, api_id, models.RoleDelete)
	if priErr != nil {
		return priErr
	}
	if len(allowList) == 0 {

		return nil
	}
	priErr = models.UPVTaskContentCollection.Remove(queryBson)
	if priErr != nil {
		return priErr
	}
	return nil
}

//DeleteUPVTaskContent 删除task_content 集合
func DeleteUPVTaskContentList(c echo.Context) (err error) {
	defer models.ErrorHandler(c)
	var currentUser models.UserWithPirvilege
	currentUser = models.CheckLogin(c)
	api_id := models.GetJumeiApiIDByPath(c.Request().Method(), c.Path())
	operationListIDStr := c.FormValue("idlist")
	operationListID := strings.Split(operationListIDStr, ",")

	for _, operationidstr := range operationListID {
		err = delteUPVTaskContent(currentUser, api_id, string(operationidstr))

		models.CheckError(err)
	}
	allowList, priErr := models.CheckUserPrivilege(&currentUser, models.TableJumeiAPI, api_id, models.RoleRead)
	models.CheckError(priErr)
	if len(allowList) == 0 {
		c.JSON(http.StatusOK, models.ExportJson(models.Right_Status, currentUser, []int{}, -1))
		return
	}

	var result []interface{}
	query := models.UPVTaskContentCollection.Find(nil)
	totalCount, countErr := query.Count()
	models.CheckError(countErr)
	err = query.Limit(10).All(&result)
	models.CheckError(err)
	c.JSON(http.StatusOK, models.ExportJson(models.Right_Status, nil, result, int64(totalCount)))
	return nil
}

//DeleteUPVUserTaskList 删除 user_task 集合
func DeleteUPVUserTaskList(c echo.Context) (err error) {
	defer models.ErrorHandler(c)
	var currentUser models.UserWithPirvilege
	currentUser = models.CheckLogin(c)
	api_id := models.GetJumeiApiIDByPath(c.Request().Method(), c.Path())
	operationListIDStr := c.FormValue("idlist")
	operationListID := strings.Split(operationListIDStr, ",")

	for _, operationidstr := range operationListID {
		err = delteUPVUserTask(currentUser, api_id, string(operationidstr))
		models.CheckError(err)
	}
	allowList, priErr := models.CheckUserPrivilege(&currentUser, models.TableJumeiAPI, api_id, models.RoleRead)
	models.CheckError(priErr)
	if len(allowList) == 0 {
		c.JSON(http.StatusOK, models.ExportJson(models.Right_Status, currentUser, []int{}, -1))
		return
	}

	var result []interface{}
	query := models.UPVUserTaskCollection.Find(nil)
	totalCount, countErr := query.Count()
	models.CheckError(countErr)
	err = query.Limit(10).All(&result)
	models.CheckError(err)
	c.JSON(http.StatusOK, models.ExportJson(models.Right_Status, nil, result, int64(totalCount)))
	return nil
}

//UploadUpvFile 通过上传包含用户更新app补丁的数组txt
func UploadUpvEventFile(c echo.Context) error {
	defer models.ErrorHandler(c)

	//过滤参数
	AppverStart := strings.Trim(c.FormValue("appverStart"), " ")
	AppverEnd := strings.Trim(c.FormValue("appverEnd"), " ")
	BundleID := strings.Trim(c.FormValue("bundleId"), " ")
	System := strings.Trim(c.FormValue("system"), " ")
	OSVersionStart := strings.Trim(c.FormValue("osversionStart"), " ")
	OSVersionEnd := strings.Trim(c.FormValue("osversionEnd"), " ")
	Brand := strings.Trim(c.FormValue("brand"), " ")
	Model := strings.Trim(c.FormValue("model"), " ")

	var sys []int
	if System != "" {
		for _, v := range strings.Split(System, ",") {
			if v != "" {
				value, err := strconv.Atoi(v)
				if err != nil {
					c.JSON(http.StatusServiceUnavailable, "客户端系统参数错误，请检查是否正确")
				}
				sys = append(sys, value)
			}
		}
	}


	eventContent := strings.Trim(c.FormValue("eventContentInput"), " ")
	useridFileHeader, err := c.FormFile("useridFile")
	if err != nil {
		c.JSON(http.StatusServiceUnavailable, err.Error())
	}
	useridFile, fileErr := useridFileHeader.Open()
	if fileErr != nil {
		c.JSON(http.StatusServiceUnavailable, fileErr.Error())
	}
	fd, fderr := ioutil.ReadAll(useridFile)
	if fderr != nil {
		c.JSON(http.StatusServiceUnavailable, fderr.Error())
	}
	allUserIDListStr := string(fd)
	allUserIDList := strings.Split(allUserIDListStr, ",")
	taskProtoNew := taskprocess.TaskInQueue{}
	taskProtoNew.Type = taskprocess.TaskTypeEvent
	var useridList []string
	checkMap := make(map[string]bool)
	if allUserIDListStr == "*" {
		useridList = append(useridList, "*")
	} else {
		for _, useridstr := range allUserIDList {

			matched, matcherr := regexp.Match(models.Conf.NsqUpv.Nsq_upv_uid_regexp, []byte(useridstr))
			if matcherr != nil {
				c.JSON(http.StatusServiceUnavailable, matcherr.Error())
				return nil
			}
			if matched == false {
				c.JSON(http.StatusServiceUnavailable, "上传文件uid文件格式不符合!")
				return nil

			}
			if _, ok := checkMap[useridstr]; !ok {
				checkMap[useridstr] = true
				useridList = append(useridList, useridstr)
			}

		}

	}
	var lable string = "EventLable"
	eventTask := &taskprocess.EventTask{}
	eventTask.TargetUID = useridList
	eventTask.Content = &eventContent
	eventTask.Label = &lable

	//过滤条件
	eventTask.Appver = [2]string{AppverStart, AppverEnd}
	if BundleID != "" {
		eventTask.BundleIds = strings.Split(BundleID, ",")
	}
	eventTask.System = sys
	eventTask.OSVersion = [2]string{OSVersionStart, OSVersionEnd}
	if Brand != "" {
		eventTask.Brand = strings.Split(Brand, ",")
	}
	if Model != "" {
		eventTask.Model = strings.Split(Model, ",")
	}



	rb, schemaerr := msgpack.Marshal(eventTask)
	if schemaerr != nil {
		c.JSON(http.StatusServiceUnavailable, schemaerr.Error())
	}
	taskProtoNew.RawBytes = rb
	tb, tberr := msgpack.Marshal(taskProtoNew)
	if tberr != nil {
		c.JSON(http.StatusServiceUnavailable, tberr.Error())
	}
	nsqerr := models.PushUPV2NSQ(tb)
	if nsqerr != nil {
		c.JSON(http.StatusServiceUnavailable, nsqerr.Error())
	}
	currentUser := models.CheckLogin(c)
	if allUserIDListStr == "*" {
		models.AppendLog(&currentUser, "加入推送队列的人数:*", models.LOG_TYPE_PUSH_EVENT)
		c.JSON(http.StatusOK, "主动推送Event:"+*eventTask.Content+"的成功数目为:*")
	} else {
		models.AppendLog(&currentUser, "加入推送队列的人数:"+strconv.Itoa(len(useridList)), models.LOG_TYPE_PUSH_EVENT)
		c.JSON(http.StatusOK, "主动推送Event:"+*eventTask.Content+"的成功数目为:"+strconv.Itoa(len(useridList)))
	}
	return nil
}
